/**************************************************************************************
*
*	Copyright (C) 2010 - 2012 Brent Andrew O. Chua - See LICENSE.txt for more info.
*		
*	Filename	-	WindowView.h
*
*	Description -	Views that actually contains the content to be drawn. Used by the
*					Window to be managed.
*
*	Comments	-	
*
*	Modification History:
*			Name			   Date					Description
*			MrCodeSushi	-	04/08/2013	-	Creation of this file
**************************************************************************************/
#ifndef _PSX_WINDOW_VIEW_H_
#define _PSX_WINDOW_VIEW_H_

#include "PulseSTD.h"
#include "String.h"
#include "EventSystem.h"
//#include "RenderEntryWindowViewPresent.h"

namespace Pulse
{
	class WindowView
	{
	public:

		void Update( const FLOAT dt );

		void Render( void );

		// So that we can have the chance of passing some WindowView specific paramters
		void OnSceneRender( RenderView *pView );

		// Present the content of the view to the Window
		void RenderToWindow( RenderView *pView );	

		const CHAR * GetName( void ) const { return m_name.GetBuffer(); }

		//Texture2D * GetRenderTexture( void );

		const SIZE_T GetWidth( void ) const { return m_width; }

		const SIZE_T GetHeight( void ) const { return m_height; }

		Scene * GetScene( void ) { return m_pScene; }

		Texture2D * GetRenderTexture( void );

	public:

		// Event management

		EventSystem * GetEventSystem( void ) { return &m_eventSystem; }

		// this, class member function
		// NOTE: WARNING! Make sure the func method accepts an EventPtr parameter. NOT IEvent*!
		template < typename ThisObject, typename Function >
		BOOL AddListener( const EEvent::Type event, ThisObject thisObject, Function func );

		// this, class member function
		// NOTE: WARNING! Make sure the func method accepts an EventPtr parameter. NOT IEvent*!
		template < typename ThisObject, typename Function >
		BOOL RemoveListener( const EEvent::Type event, ThisObject &thisObject, Function func );

		void TriggerEvent( IEvent *pEvent );

		void PostEvent( EventPtr pEvent );

	protected:

		virtual EErrorCode::Type OnInitialize( void ) { return EErrorCode::OKAY; }

		virtual void OnCleanup( void ) { return; }

	private:

		friend WindowingSystem;
		friend Window;
		friend RenderPathLightPrePass;

		static EErrorCode::Type Create( const CHAR *pViewName, WindowView **ppOut );

		static void Delete( WindowView *pView );

	private:

		WindowView( const CHAR *pViewName );

		virtual ~WindowView( void );

		WindowView( const WindowView & ); // No-op

		WindowView & operator = ( const WindowView &rhs ); // No-op

		EErrorCode::Type Initialize( void );

		void Cleanup( void );

		void SetOwner( Window *pOwner );

		Window * GetOwner( void ) { return m_pWindowOwner; }

		EErrorCode::Type ResetOrientation( const FLOAT ratioX, const FLOAT ratioY, 
			const FLOAT ratioWidth, const FLOAT ratioHeight );

		// Called to use the same size and pos ratio
		EErrorCode::Type ResetOrientation( void );

		EErrorCode::Type UpdateRenderInfo( void );

	private:

		// Utility Methods
		//////////////////

		void ReleaseWindowViewRenderData( void );

		//void ReleaseRenderTexture( void );

		//EErrorCode::Type RecreateRenderTexture( const SIZE_T width, const SIZE_T height );

	private:

		// Input system delegates
		//////////////////////////

		void OnKeyUp( IEvent *pEvent );

		void OnKeyDown( IEvent *pEvent );

		void OnMouseMove( IEvent *pEvent );

		void OnMouseButtonUp( IEvent *pEvent );

		void OnMouseButtonDown( IEvent *pEvent );

	private:

		String m_name;

		// Actual size this view holds
		FLOAT m_ratioPosX;
		FLOAT m_ratioPosY;
		FLOAT m_ratioWidth;
		FLOAT m_ratioHeight;

		// Calculated from the ratio sizes above
		SIZE_T m_posX;
		SIZE_T m_posY;
		SIZE_T m_width;
		SIZE_T m_height;

		Window		*m_pWindowOwner;
		Scene		*m_pScene;
		EventSystem	m_eventSystem;

		// Render information for the scene
		RenderEntryBindParameters *m_pRESceneParams;

		// Render information needed to present to the parent Window
		RenderEntryViewport				*m_pREViewport;
		RenderEntryWindowViewPresent	*m_pREWVPresent;
		Texture2D						*m_pRenderTexture;
		Material						*m_pMaterial;
		Geometry						*m_pGeometry;
		Model							*m_pModel;
	};

	// this, class member function
	template < typename ThisObject, typename Function >
	PSX_INLINE BOOL WindowView::AddListener( const EEvent::Type event, ThisObject thisObject, Function func )
	{
		return m_eventSystem.AddListener< ThisObject, Function>( event, thisObject, func );
	}

	// this, class member function
	template < typename ThisObject, typename Function >
	PSX_INLINE BOOL WindowView::RemoveListener( const EEvent::Type event, ThisObject &thisObject, Function func )
	{
		return m_eventSystem.RemoveListener( event, thisObject, func );
	}

	PSX_INLINE void WindowView::TriggerEvent( IEvent *pEvent )
	{
		m_eventSystem.TriggerEvent( pEvent );
	}

	PSX_INLINE void WindowView::PostEvent( EventPtr pEvent )
	{
		m_eventSystem.PostEvent( pEvent );
	}
}

#endif /* _PSX_WINDOW_VIEW_H_ */